<?php

require_once './Template/Compiler/ACompiler.php';

class Compiler extends Template\Compiler\ACompiler {}

class CTransformer {

    /**
     * @param array $content
     * @param array $namespace
     * @param array $extends
     * @return array
     */
    public function createClassOpen (array &$content, array $namespace, array $extends) {
        $namespace = implode('\\', (array) $namespace);
        $extends = implode('\\', (array) $extends);
        $extends = $extends !== '' ? $extends : 'Template\\ATemplate';
        array_push($content, '<?php');
        array_push($content, '');
        array_push($content, sprintf('namespace Templates\\%1$s;', implode('\\', (array) $namespace)));
        array_push($content, '');
        array_push($content, '/**');
        array_push($content, ' * Класс шаблона.');
        array_push($content, ' */');
        array_push($content, sprintf('class CTemplate extends Templates\\%1$s {', $extends));
        array_push($content, '');
        return $content;
    }

    /**
     * @param array $content
     * @return array
     */
    public function createClassClose (array &$content) {
        array_push($content, '}');
        array_push($content, '');
        return $content;
    }

    public function createTemplateOpen (array &$content, $name) {
        // TODO: в контенте нарисовать нарисовать название шаблона!!!
        array_push($content, '    /**');
        array_push($content, '     * Шаблон.');
        array_push($content, '     * ');
        array_push($content, '     * @param array $params');
        array_push($content, '     * @param \DOMDocument $document');
        array_push($content, '     * @return \DOMNodeList');
        array_push($content, '     */');
        array_push($content, sprintf('    protected function template%1$s (array &$params, \DOMDocument $document = null) {', $name));
        array_push($content, '        if ($document === null) { $document = $this->getDocument(); }');
        array_push($content, '        $template = $document->createElement(\'template\');');
        array_push($content, '        $context = array($template);');
        return $content;
    }

    public function createTemplateClose (array &$content) {
        array_push($content, '        return $template->childNodes;');
        array_push($content, '    }');
        array_push($content, '');
        return $content;
    }

    const PARAM_INTEGER = 'integer';
    const PARAM_FLOAT   = 'float';
    const PARAM_STRING  = 'string';
    const PARAM_BOOLEAN = 'boolean';
    const PARAM_LIST    = 'list';
    const PARAM_OBJECT  = 'object';

    public function createTemplateParam (array &$content, $name, $type, $default = null) {
        switch (strtolower(trim($type))) {
            case static::PARAM_INTEGER :
                $default = $default !== null ? (integer) $default : $default;
                array_push($content, sprintf('        $param[%1$s] = isset($param[%1$s]) ? (integer) $param[%1$s] : %2$s;', var_export((string) $name, true), var_export($default, true)));
                break;
            case static::PARAM_FLOAT :
                $default = $default !== null ? (float) $default : $default;
                array_push($content, sprintf('        $param[%1$s] = isset($param[%1$s]) ? (float) $param[%1$s] : %2$s;', var_export((string) $name, true), var_export($default, true)));
                break;
            case static::PARAM_BOOLEAN :
                if ($default !== null) {
                    if (is_string($default)) {
                        $default = !in_array(strtolower(trim((string) $default)), array('false', 'off', 'no'));
                    } elseif (is_numeric($default)) {
                        $default = (boolean) (((float) $default) > 0);
                    } elseif (!is_bool($default)) {
                        $default = (boolean) $default;
                    }
                }
                array_push($content, sprintf('        if (isset($param[%1$s])) {', var_export((string) $name, true)));
                array_push($content, sprintf('            if (is_string($param[%1$s])) {', var_export((string) $name, true)));
                array_push($content, sprintf('                $param[%1$s] = !in_array(strtolower(trim((string) $param[%1$s])), array(\'false\', \'off\', \'no\'));', var_export((string) $name, true)));
                array_push($content, sprintf('            } elseif (is_numeric($param[%1$s])) {', var_export((string) $name, true)));
                array_push($content, sprintf('                $param[%1$s] = (boolean) (((float) $param[%1$s]) > 0);', var_export((string) $name, true)));
                array_push($content, sprintf('            } elseif (!is_bool($param[%1$s])) {', var_export((string) $name, true)));
                array_push($content, sprintf('                $param[%1$s] = (boolean) $param[%1$s];', var_export((string) $name, true)));
                array_push($content,         '            }');
                array_push($content,         '        } else {');
                array_push($content, sprintf('            $param[%1$s] = %2$s;', var_export((string) $name, true), var_export($default, true)));
                array_push($content,         '        }');
                break;
            case static::PARAM_LIST :
                $default = $default !== null ? array_map(function ($value) {
                    return preg_replace(array('#^\\s+#', '#\\s+#', '#\\s+$#'), array('', ' ', ''), $value);
                }, explode(',', (string) $default)) : $default;
                array_push($content, sprintf('        $param[%1$s] = isset($param[%1$s]) ? array_values((array) $param[%1$s]) : %2$s;', var_export((string) $name, true), str_replace(array("(\n  ", ",\n  ", ",\n)"), array('(', ', ', ')'), var_export($default, true))));
                break;
            case static::PARAM_OBJECT :
                array_push($content, sprintf('        $param[%1$s] = isset($param[%1$s]) ? (object) (array) $param[%1$s] : (object) array();', var_export((string) $name, true)));
                break;
            case static::PARAM_STRING :
            default :
                $default = $default !== null ? (string) $default : $default;
                array_push($content, sprintf('        $param[%1$s] = isset($param[%1$s]) ? (string) $param[%1$s] : %2$s;', var_export((string) $name, true), var_export($default, true)));
                break;
        }
        return $content;
    }

    public function createElementOpen (array &$content) {}

    public function createElementClose (array &$content) {}

}

$compiler = new Compiler('./Template/Compiler/example.xml');

$compiler->compile();
